<?php

defined('ROOT') || die('Please define ROOT constant');

class Loader
{
    private static $configs = FALSE;

    public static function format($name, $type = 'controller')
    {
        $name = Loader::filter($name);
        if ($type == 'controller') {
            return ucfirst($name) . 'Controller';
        } elseif ($type == 'action') {
            return $name;
        } else {
            return ucfirst($name);
        }
    }

    public static function getLogFile($type = 'error')
    {
        $type .= '_log_file';
        if (($file = self::getConfig('app', $type)) === FALSE) {
            throw new Exception("Nhận đường dẫn tập tin log [$type] thất bại");
        }
        $file = ROOT . self::getConfig('app', 'log_dir') . $file;
        return $file;
    }

    # Loại bỏ những ký tự đặc biệt ra khỏi tên Controller, Action
    private static function filter($name)
    {
        $special_char = array(
            '-' => null
        );

        $name = str_replace(array_keys($special_char), array_values($special_char), $name);

        return $name;
    }

    public static function &loadController($name, $action, $formatted = false)
    {
        $result = FALSE;
        $formatted || $name = self::format($name);
        if (self::loadClass($name)) {
            if (method_exists($name, $action)) {
                $controller = new $name($action, true);
                $result = $controller;
            }
        }

        return $result;
    }

    public static function callAction($controller, $action, $params)
    {
        $object = Loader::loadController($controller, $action);
        if ($object !== FALSE && method_exists($object, $action)) {
            $object->$action($params);
            return TRUE;
        } else {
            return FALSE;
        }
    }

    private static function loadConfig()
    {
        if (self::$configs !== FALSE) {
            return;
        }

        isset($config) || $config = array();
        foreach (glob(ROOT . 'configs/*.php') as $fileName) {
            require_once $fileName;
        }

        self::$configs = $config;
        unset($config);
    }

    /**
     * @static
     * @param string $group
     * @param string $item
     * @return array
     */
    public static function getConfig($group = '', $item = '')
    {
        self::loadConfig();
        if ($group == '') {
            return self::$configs;
        }

        if (!isset(self::$configs[$group])) {
            return FALSE;
        } elseif ($item == '') {
            return self::$configs[$group];
        } elseif (!isset(self::$configs[$group][$item])) {
            return FALSE;
        } else {
            return self::$configs[$group][$item];
        }
    }

    public static function setConfig($group, $item = null, $value = array())
    {
        self::loadConfig();
        if ($item == null) {
            self::$configs[$group] = $value;
        } else {
            isset(self::$configs[$group]) || self::$configs[$group] = array();
            self::$configs[$group][$item] = $value;
        }
    }

    public static function loadClass($class)
    {
        if (class_exists($class, false)) {
            return true;
        }

        $fileName = strtolower($class) . '.class.php';

        defined('LIB_DIR') || define('LIB_DIR', ROOT . 'library/');
        defined('MODELS_DIR') || define('MODELS_DIR', ROOT . 'application/models/');
        defined('CONTROLLERS_DIR') || define('CONTROLLERS_DIR', ROOT . 'application/controllers/');

        # Load class from LIB_DIR
        if (file_exists(LIB_DIR . $fileName)) {
            require_once LIB_DIR . $fileName;
            if (class_exists($class)) {
                return true;
            }
        } elseif (file_exists(CONTROLLERS_DIR . $fileName)) {
            require_once CONTROLLERS_DIR . $fileName;
            if (class_exists($class)) {
                return true;
            }
        } elseif (file_exists(MODELS_DIR . $fileName)) {
            require_once MODELS_DIR . $fileName;
            if (class_exists($class)) {
                return true;
            }
        }

        return FALSE;
    }

}